/*
 * Copyright © 2019-2020  Whale Cloud, Inc. All Rights Reserved.
 *
 * Notice: Whale Cloud Inc copyrights this specification.
 * No part of this specification may be reproduced in any form or means,
 * without the prior written consent of Whale Cloud Inc.
 *
 */
package com.wteam.modules.system.service.impl;

import com.wteam.modules.system.domain.Student;
import com.wteam.modules.system.domain.dto.CusPage;
import com.wteam.modules.system.domain.dto.StudentDTO;
import com.wteam.modules.system.domain.mapper.CourseMapper;
import com.wteam.modules.system.domain.mapper.StudentMapper;
import com.wteam.modules.system.domain.mapper.UserMapper;
import com.wteam.modules.system.repository.CourseRepository;
import com.wteam.modules.system.repository.StudentRepository;
import com.wteam.modules.system.repository.UserRepository;
import com.wteam.modules.system.service.StudentCourseMapService;
import com.wteam.modules.system.domain.StudentCourseMap;
import com.wteam.modules.system.domain.dto.StudentCourseMapDTO;
import com.wteam.modules.system.domain.criteria.StudentCourseMapQueryCriteria;
import com.wteam.modules.system.domain.mapper.StudentCourseMapMapper;
import com.wteam.modules.system.repository.StudentCourseMapRepository;
import com.wteam.exception.BadRequestException;
import com.wteam.utils.*;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.cache.annotation.*;
import lombok.RequiredArgsConstructor;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * 学生课程映射 业务实现层.
 *
 * @author herry_wong
 * @since 2020-12-29
 */
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "studentCourseMap")
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class StudentCourseMapServiceImpl implements StudentCourseMapService {

    private final StudentCourseMapRepository studentCourseMapRepository;

    private final StudentCourseMapMapper studentCourseMapMapper;

    private final StudentRepository studentRepository;
    private final StudentMapper studentMapper;

    private final CourseRepository courseRepository;
    private final CourseMapper courseMapper;

    private final UserRepository userRepository;
    private final UserMapper userMapper;

    private final RedisUtils redisUtils;

    @Override
    public Map<String,Object> queryAll(StudentCourseMapQueryCriteria criteria, Pageable pageable){
        Page<StudentCourseMap> page = studentCourseMapRepository.findAll((root, criteriaQuery, criteriaBuilder) ->  QueryHelper.andPredicate(root, criteria, criteriaBuilder), pageable);
        Page<StudentCourseMapDTO> studentCourseMapDTOPage = page.map(studentCourseMapMapper::toDto);
        Page<StudentCourseMapDTO> cusPage = new CusPage<>(studentCourseMapDTOPage);
        for (StudentCourseMapDTO studentCourseMapDTO: cusPage){
            Collections.replaceAll(cusPage.getContent(),
                    studentCourseMapDTO,
                    findDTOById(studentCourseMapDTO.getId()));
        }
        return PageUtil.toPage(cusPage);
    }

    @Override
    public List<StudentCourseMapDTO> queryAll(StudentCourseMapQueryCriteria criteria){
        return studentCourseMapMapper.toDto(studentCourseMapRepository.findAll((root, criteriaQuery, criteriaBuilder) ->  QueryHelper.andPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
//    @Cacheable(key = "'id:' + #p0")
    public StudentCourseMapDTO findDTOById(Long id) {
        StudentCourseMap studentCourseMap = studentCourseMapRepository.findById(id).orElse(null);
        ValidUtil.notNull(studentCourseMap, StudentCourseMap.ENTITY_NAME, "id", id);
        StudentCourseMapDTO studentCourseMapDTO = studentCourseMapMapper.toDto(studentCourseMap);
        studentCourseMapDTO.setStudentDTO(
                studentMapper.toDto(studentRepository.findById(studentCourseMapDTO.getStudentId()).orElse(null))
        );
        studentCourseMapDTO.setCourseDTO(
                courseMapper.toDto(courseRepository.findById(studentCourseMapDTO.getCourseId()).orElse(null))
        );
        studentCourseMapDTO.getStudentDTO().setUserDTO(
                userMapper.toDto(userRepository.findById(studentCourseMapDTO.getStudentId()).orElse(null))
        );
        return studentCourseMapDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudentCourseMapDTO create(StudentCourseMap resources) {
        StudentCourseMapDTO studentCourseMapDTO = new StudentCourseMapDTO();
        if (studentCourseMapRepository.findByStudentIdAndCourseId(resources.getStudentId(),resources.getCourseId())
         == null){
            studentCourseMapDTO = studentCourseMapMapper.toDto(studentCourseMapRepository.save(resources));
            studentCourseMapDTO.setCourseDTO(
                    courseMapper.toDto(courseRepository.findById(resources.getCourseId()).orElse(null))
            );
            studentCourseMapDTO.setStudentDTO(
                    studentMapper.toDto(studentRepository.findById(resources.getStudentId()).orElse(null))
            );
            studentCourseMapDTO.getStudentDTO().setUserDTO(
                    userMapper.toDto(userRepository.findById(studentCourseMapDTO.getStudentId()).orElse(null))
            );
        }else{
            studentCourseMapDTO.setMsg("该学生已有该课程");
        }
        return studentCourseMapDTO;
    }

    @Override
    @CacheEvict(key = "'id:' + #p0.id")
    @Transactional(rollbackFor = Exception.class)
    public void update(StudentCourseMap resources) {
        StudentCourseMap studentCourseMap = studentCourseMapRepository.findById(resources.getId()).orElse(null);
        ValidUtil.notNull(studentCourseMap, StudentCourseMap.ENTITY_NAME, "id",resources.getId());

        studentCourseMap.copy(resources);
        studentCourseMapRepository.save(studentCourseMap);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(Set<Long> ids) {
        redisUtils.delByKeys("studentCourseMap::id:", ids);
        studentCourseMapRepository.logicDeleteInBatchById(ids);
    }

    @Override
    public void download(List<StudentCourseMapDTO> queryAll, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (StudentCourseMapDTO studentCourseMap : queryAll) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("学生id", studentCourseMap.getStudentId());
            map.put("课程id", studentCourseMap.getCourseId());
            map.put("创建时间", studentCourseMap.getCreatedAt());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    public static void main(String[] args) {
        StudentDTO student1 = new StudentDTO();
        StudentDTO student2 = new StudentDTO();
        StudentDTO student3 = new StudentDTO();
        student1.setUid(1L);
        student2.setUid(2L);
        student3.setUid(3L);
        List<StudentDTO> studentDTOS = new ArrayList<>();
        studentDTOS.add(student1);
        studentDTOS.add(student2);
        for (StudentDTO studentDTO: studentDTOS){
            Collections.replaceAll(studentDTOS,studentDTO,student3);
        }
        System.out.println(studentDTOS);
//        List<Integer> a = new LinkedList<>();
//        a.add(1);
//        a.add(2);
//        for (Integer integer: a){
//            Collections.replaceAll(a,2,3);
//        }

//        System.out.println(a);
    }
}